package com.cctc.juc.source.Bitc.Icontainer.hash;


import java.io.Serializable;

/**
 * [LongAdder 原子计数器] 实现类。
 * 概述：LongAdder 是一个非常高效的高并发原子类，采用了 “热点分散” 思想对 AtomicLong 进行优化，以提升 AtomicLong 的并发访问效率。
 * 对于 AtomicLong 来说，内部使用一个 value 属性保存着实际的 long 值，所有的操作都是针对该 value 值进行的。当线程争用激烈的场景下，该 value 值其实就是一个并发访问热点，就会导致 CAS “空自旋” 问题，造成 CPU 性能损耗。
 * LongAdder 针对该问题，采用 “热点分散” 的思想，对其进行优化，核心逻辑主要由其父类 Striped64 进行实现。
 * Striped64 是一个基于 Cell 数组构建的哈希表，Cell 单元格作为 Striped64 中的一个内部类，拥有一个 volatile 修饰的 value 属性，且只允许通过 cas 机制进行原子操作。
 * 在线程争用激烈的场景下，我们可以将 AtomicLong 类型的 value 热点值分散到一个 Cell 数组中，基于哈希函数为每个线程（基于其内部的 threadLocalRandomProbe 属性）计算一个随机散列值，从而将其定位到 Cell 数组的不同单元格（哈希槽）内，如果出现冲突，将采用 {开放地址法 -> 双重探测（和 ThreadLocalMap 一样，避免内存泄露）} 寻找下一个可用槽位，各个线程只对自己槽中的子 value 值进行 CAS 操作，如果要获得完整的 value 值，只需要将各个槽中的子 value 值累加起来即可。
 * 这样一来，AtomicLong 类型的 value 热点值就被分散了，在保证线程安全的前提下，有效提升了 AtomicLong 的并发访问效率。
 */
public class E1LongAdder_AAAAA extends E0Striped64_AAAAA implements Serializable {
    private static final long serialVersionUID = -4057421517488566381L;

    public E1LongAdder_AAAAA() {
    }

    // --- [常用方法] --- //

    /**
     * [添加 | 更新] 操作。
     * - 将给定值相加至 Base 基础值或指定 Cell 单元格内。
     * 算法过程：
     * 1）默认将给定值相加至 Base 基础值。
     * - 默认情况下，cells 数组为空，直接更新到 base 基础值，如果更新失败，说明产生了第一次争用冲突，需要对 cells 数组进行初始化，进入内层循环，执行步骤 2）。
     * 2）执行 longAccumulate 方法，将给定值相加至指定 Cell 单元格内，进行热点分散。
     */
    public void add(long update) {
        Cell[] cs;
        int n;
        long b, expect;
        Cell c;
        /**
         * CASE 1：将给定值相加至 Base 基础值。
         * - 默认情况下，cells 数组为空，如果 cells 数组不为空，说明之前存在争用，直接更新到 base 基础值，如果更新失败，说明产生了第一次争用冲突，需要对 cells 数组进行初始化，进入内层循环。
         */
        if ((cs = cells) != null || !casBase(b = base, b + update)) {
            boolean unContended = true;
            /**
             * CASE 2: 将给定值相加至指定 Cell 单元格内。
             * - 2.1 如果 cells 数组还没有初始化；
             * - 2.2 或者当前线程的哈希值在 cells 数组映射位置的 Cell 对象为 null；
             * - 2.3 或者在该 Cell 对象上进行 CAS 更新操作；
             * - 2.4 或者更新失败，表示存在争用，执行 longAccumulate 方法，进行热点分散。
             */
            if (cs == null || (n = cs.length - 1) < 0 ||
                    (c = cs[getRandomProbe() & n]) == null ||
                    !(unContended = c.cas(expect = c.value, expect + update))) {
                longAccumulate(update, null, unContended);
            }
        }
    }

    /**
     * [求和] 操作。
     * - 如果要获得完整的 value 值，只需要将各个槽中的变量值（Cell.value）累加起来，返回最终的累加结果即可。
     */
    public long sum() {
        Cell[] cs;
        Cell c;
        long sum = base;
        if ((cs = cells) != null) {
            for (int i = 0; i < cs.length; i++) {
                if ((c = cs[i]) != null) {
                    sum += c.value;
                }
            }
        }
        return sum;
    }

    // --- [其他方法] --- //

    public long sumThenReset() {
        Cell[] cs;
        Cell c;
        long sum = base;
        base = 0L;
        if ((cs = cells) != null) {
            for (int i = 0; i < cs.length; i++) {
                if ((c = cs[i]) != null) {
                    sum += c.value;
                    c.value = 0L;
                }
            }
        }
        return sum;
    }

    public void increment() {
        add(1L);
    }

    public void decrement() {
        add(-1L);
    }

    public void reset() {
        Cell[] cs;
        Cell c;
        base = 0L;
        if ((cs = cells) != null) {
            for (int i = 0; i < cs.length; i++) {
                if ((c = cs[i]) != null) {
                    c.value = 0L;
                }
            }
        }
    }

    @Override
    public int intValue() {
        return (int) sum();
    }

    @Override
    public long longValue() {
        return sum();
    }

    @Override
    public float floatValue() {
        return (float) sum();
    }

    @Override
    public double doubleValue() {
        return (double) sum();
    }
}
